package cn.mujiankeji.mbrowser.功能.浏览框

import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import cn.mujiankeji.mbrowser.功能.浏览框.webview.MWebView
import cn.mujiankeji.mbrowser.工具.mlog
import cn.mujiankeji.mbrowser.数据.枚举类.代码类型枚举
import cn.mujiankeji.mbrowser.界面.图标.MyIconPack
import cn.mujiankeji.mbrowser.界面.图标.myiconpack.全屏
import cn.mujiankeji.mbrowser.界面.图标.myiconpack.关闭
import cn.mujiankeji.mbrowser.界面.图标.myiconpack.父级
import cn.mujiankeji.mbrowser.界面.图标.myiconpack.选择元素
import cn.mujiankeji.mbrowser.界面.组件.代码框.代码格式化类型
import cn.mujiankeji.mbrowser.界面.组件.代码框.代码格式化视图
import cn.mujiankeji.mbrowser.界面.组件.代码框.代码编辑回调
import kotlinx.coroutines.launch
import 界面.弹窗.下拉菜单
import 界面.弹窗.下拉菜单项目

/**
 * 浏览框视图组件
 * 
 * 负责显示网页内容，并提供页面内容搜索和元素审查功能
 * 核心职责是网页内容的渲染，UI元素由调用方负责
 */
@Composable
fun 浏览框视图(state: 浏览框状态,modifier: Modifier = Modifier.fillMaxSize()) {
    state.coroutine = rememberCoroutineScope()
    DisposableEffect(Unit) {
        onDispose {
            state.coroutine = null
        }
    }

    Column(modifier) {
        // 页内搜索 -- 搜索页面内容
        if (state.启用页面内容搜索 && !state.启用开发者模式) {
            页面内容搜索视图(state)
        }

        Box(Modifier.weight(1f).fillMaxWidth()
            .background(Color.Red)) {
            // 使用key确保WebView不会因为周围Compose状态变化而重新创建
            Webview(
                state = state,
                modifier = Modifier.fillMaxSize().background(Color.Blue)
            )
        }

        // 审查元素
        if (state.启用开发者模式) {
            审查元素视图(state)
        }
    }
}

/**
 * 页面内容搜索视图
 * 实现页面内文本搜索功能
 */
@Composable
private fun 页面内容搜索视图(state: 浏览框状态) {
    var 搜索文本 by remember { mutableStateOf("") }
    val focusRequester = remember { FocusRequester() }

    LaunchedEffect(state.启用页面内容搜索) {
        搜索文本 = ""
        if (!state.启用页面内容搜索){
            state.关闭页面内容搜索()
        }
    }
    LaunchedEffect(搜索文本) {
        state.webview?.findAllAsync(搜索文本)
    }

    Surface(
        modifier = Modifier.fillMaxWidth(),
        shadowElevation = 4.dp
    ) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(8.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            // 搜索输入框
            OutlinedTextField(
                value = 搜索文本,
                onValueChange = { 
                    搜索文本 = it
                    state.执行页面内容搜索(搜索文本)
                },
                modifier = Modifier
                    .weight(1f)
                    .focusRequester(focusRequester),
                placeholder = { Text("在页面中查找...") },
                singleLine = true,
                keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
                keyboardActions = KeyboardActions(
                    onSearch = {
                        state.执行页面内容搜索(搜索文本)
                    }
                )
            )
            
            Spacer(modifier = Modifier.width(8.dp))
            
            // 向上查找按钮
            IconButton(onClick = { state.执行页面内容搜索(搜索文本, false) }) {
                Icon(Icons.Default.KeyboardArrowUp, contentDescription = "向上查找")
            }
            
            // 向下查找按钮
            IconButton(onClick = { state.执行页面内容搜索(搜索文本, true) }) {
                Icon(Icons.Default.KeyboardArrowDown, contentDescription = "向下查找")
            }
            
            // 关闭搜索按钮
            IconButton(onClick = { state.关闭页面内容搜索() }) {
                Icon(Icons.Default.Close, contentDescription = "关闭搜索")
            }
        }
    }
    
    // 自动获取焦点
    LaunchedEffect(Unit) {
        focusRequester.requestFocus()
    }
}


/**
 * Webview视图
 * 负责网页内容的渲染和显示
 */
@Composable
private fun Webview(state: 浏览框状态, modifier: Modifier) {
    val context = LocalContext.current

    // 使用remember缓存WebView实例，确保即使Compose重组也不会重新创建WebView
    val webView = remember(state.uuid) {
        if (state.webview == null) {
            state.webview = MWebView(context, state).apply {
                // 设置clipToOutline解决WebView加载完成但不显示的问题
                clipToOutline = true
            }

        }
        state.webview!!
    }
    var 已加载 by remember(state.uuid) { mutableStateOf(false) }

    LaunchedEffect(state.是否暂停.collectAsState()) {
        if (!state.是否暂停.value && !已加载 && state.浏览框创建完毕() && state.页面配置.起始地址.isNotEmpty()){
            已加载 = true
            state.加载(state.页面配置.起始地址, state.页面配置.来源地址)
        }
    }
    // 使用AndroidView封装WebView，最小化update函数的工作量
    // 同时使用shouldRebuild参数避免因WebView内部状态变化导致的不必要重组
    AndroidView(
        factory = {
            try {
                val f = FrameLayout(context)
                f.setBackgroundColor(Color.Red.toArgb())
                val w = state.webview!!
                // 关键：设置LayoutParams
                val lp = FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.MATCH_PARENT,
                    FrameLayout.LayoutParams.MATCH_PARENT
                )
                w.parent?.let {
                    (it as ViewGroup).removeAllViews()
                }
                w.layoutParams = lp
                f.addView(w)
                f
            }
            finally {
                if (!state.是否暂停.value && !已加载 && state.浏览框创建完毕() && state.页面配置.起始地址.isNotEmpty()){
                    state.加载(state.页面配置.起始地址, state.页面配置.来源地址)
                    已加载 = true
                }
            }

        },
        update = { view ->
            view.removeAllViews()
            state.webview!!.let {
                it.parent?.let {
                    (it as ViewGroup).removeAllViews()
                }
                view.addView(it)
            }

            if (!state.是否暂停.value && !已加载 && state.浏览框创建完毕() && state.页面配置.起始地址.isNotEmpty()){
                已加载 = true
                state.加载(state.页面配置.起始地址, state.页面配置.来源地址)
            }
            state.继续()


        },
        modifier = modifier,
        // 关键优化：只有当WebView的关键状态(非滚动状态)变化时才重建
        onReset = {
            // 重置？ 销毁对应界面？
            state.暂停()
            webView.parent?.let { parent ->
                (parent as ViewGroup).removeView(webView)
            }
        },
        onRelease = {
            mlog("AndroidView释放",state.uuid,state.标题.value,state.webview == null)
        }
    )
}

/**
 * 元素审查视图
 * 提供开发者工具功能，审查网页元素
 */
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun 审查元素视图(state: 浏览框状态) {
    var 全屏显示 by remember { mutableStateOf(false) }
    var 格式化方式 by remember { mutableStateOf(代码类型枚举.HTML) } // 0txt 1 html格式化, 2 json 源文本
    var 显示格式化类型下拉框 by remember { mutableStateOf(false) }



    @Composable
    fun btn(icon : ImageVector,sel : Boolean = false,clickalbe: ()->Unit){
        IconButton(clickalbe) {
            Icon(icon,"",
                modifier = Modifier.size(14.dp),
                tint = if (sel) MaterialTheme.colorScheme.primary
            else MaterialTheme.colorScheme.onSurfaceVariant)
        }
    }

    Column(Modifier.fillMaxWidth().fillMaxHeight(if (全屏显示) 1f else 0.5f)) {
        Row(Modifier.fillMaxWidth().height(38.dp)
            .background(MaterialTheme.colorScheme.surfaceVariant),
            verticalAlignment = Alignment.CenterVertically)
        {

            // 属性按钮
            LazyRow(Modifier.weight(1f)) {

                // 1. 切换内容显示方式，即格式化方式，点击即下拉框切换选择
                item {
                    IconButton({
                        显示格式化类型下拉框 = !显示格式化类型下拉框
                    }){
                        Text(格式化方式.name.substring(0,1),
                            color = MaterialTheme.colorScheme.onSurfaceVariant,
                            style = MaterialTheme.typography.labelMedium)
                        下拉菜单(显示格式化类型下拉框,{显示格式化类型下拉框 = false}){
                            代码类型枚举.entries.forEach {
                                下拉菜单项目(it.name){
                                    格式化方式 = it
                                }
                            }
                        }
                    }
                }

                // 2. 选 -  是否开启可选元素
                item {
                    btn(MyIconPack.选择元素, sel = state.启用元素选择器) {
                        state.coroutine?.launch {
                            state.设置元素选择器启用状态(!state.启用元素选择器)
                        }
                    }
                }

                // 3. 父 -  取当前选中的父级 图标
                item {
                    btn(MyIconPack.父级){
                        state.coroutine?.launch {
                            if (!state.启用元素选择器){
                                state.设置元素选择器启用状态(true)
                            }
                            else{
                                state.注入脚本("javascript:m_to_parent()")
                            }
                        }
                    }
                }

                // 4. AD - 对当前元素生成 adblock规则
                // TODO AD按钮 创建拦截规则

            }

            // 全屏，关闭
            btn(MyIconPack.全屏,全屏显示) {
                全屏显示 = !全屏显示
            }
            btn(MyIconPack.关闭) {
                state.coroutine?.launch {
                    state.关闭开发者工具()
                }
            }

        }

        审查元素选中源码视图(state, 格式化方式)
    }
}

@Composable
private fun 审查元素选中源码视图(
    state: 浏览框状态,
    显示方式: 代码类型枚举,

) {
    // 代码编辑回调实现
    val 代码编辑回调实现 = remember {
        object : 代码编辑回调 {
            override fun 代码已编辑(原始代码: String, 编辑后代码: String, 节点标识: String) {
                mlog("浏览框视图: 代码已编辑，准备注入脚本更新元素，节点标识: $节点标识")
                mlog("浏览框视图: 原始代码长度: ${原始代码.length}, 编辑后代码长度: ${编辑后代码.length}")
                
                // 处理编辑后的代码，移除换行符和特殊字符
                var 处理后代码 = 编辑后代码.trim()
                处理后代码 = 处理后代码.replace("\n", "")
                处理后代码 = 处理后代码.replace("\r", "")
                
                // 转义单引号，防止JavaScript注入
                处理后代码 = 处理后代码.replace("'", "\\'")
                
                // 构建JavaScript调用，使用m_edit_element_by_path函数
                val 脚本 = "m_edit_element_by_path('$节点标识', '$处理后代码')"
                
                // 在协程中执行注入脚本
                state.coroutine?.launch {
                    mlog("浏览框视图: 开始注入脚本...")
                    state.注入脚本(脚本)
                    mlog("浏览框视图: 已注入更新元素的脚本，节点标识: $节点标识")
                }
            }
        }
    }


    if (显示方式 == 代码类型枚举.HTML){
        代码格式化视图(
            代码 = state.选中元素代码.value.value,
            类型 = 代码格式化类型.HTML,
            modifier = Modifier.fillMaxSize(),
            代码编辑回调 = 代码编辑回调实现
        )
    }
    else if (显示方式 == 代码类型枚举.JSON){
        代码格式化视图(
            代码 = state.选中元素代码.value.value,
            类型 = 代码格式化类型.JSON,
            modifier = Modifier.fillMaxSize(),
            代码编辑回调 = 代码编辑回调实现
        )
    }
    else{
        Text(
            text = state.选中元素代码.value.value,
            style = TextStyle(
                fontFamily = FontFamily.Monospace,
                fontSize = 14.sp
            ),
            modifier = Modifier
                .fillMaxSize()
                .padding(16.dp)
                .verticalScroll(rememberScrollState())
        )
    }
}